package org.jmc.refmanager.domain.dao.jpa;

import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;
import javax.persistence.Query;

import org.springframework.orm.jpa.JpaCallback;

public class PagedResultsJpaCallback<E> implements JpaCallback<List<E>> {
	final private Query query;
	final private int startIndex;
	final private int maxResults;
	final Map<String, ? extends Object> parametersMap;
	final Object[] parametersArray;

	public PagedResultsJpaCallback(final Query query, final int startIndex, final int maxResults) {
		this.query = query;
		this.maxResults = maxResults;
		this.startIndex = startIndex;
		this.parametersMap = null;
		this.parametersArray = null;
	}

	public PagedResultsJpaCallback(final Query query, final int startIndex, final int maxResults,
			final Map<String, ? extends Object> params) {
		this.query = query;
		this.maxResults = maxResults;
		this.startIndex = startIndex;
		this.parametersMap = params;
		this.parametersArray = null;
	}

	public PagedResultsJpaCallback(final Query query, final int startIndex, final int maxResults,
			final Object... params) {
		this.query = query;
		this.maxResults = maxResults;
		this.startIndex = startIndex;
		this.parametersMap = null;
		this.parametersArray = params;
	}

	@SuppressWarnings("unchecked")
	public List<E> doInJpa(final EntityManager em) throws PersistenceException {
		if (startIndex != maxResults && maxResults != 0) {
			query.setFirstResult(startIndex).setMaxResults(maxResults);
		}
		
		if (this.parametersMap != null) {
			for (String s : this.parametersMap.keySet()) {
				query.setParameter(s, this.parametersMap.get(s));
			}
		} else if (this.parametersArray != null) {
			for (int t = 0; t < this.parametersArray.length; t++) {
				query.setParameter(t+1, this.parametersArray[t]);
			}
		}
		
		return query.getResultList();
	}

}